# visual_novel.py
import tkinter as tk
from tkinter import messagebox
from PIL import Image, ImageTk
from game_core import GameCore
import os
import fight
import threading
import time
import pygame
import sys

class VisualNovelUI:
    def __init__(self, master, resource_paths, fullscreen=True):
        self.master = master
        master.title("猎手张小凡 - 完整版")
        
        if fullscreen:
            master.attributes("-fullscreen", True)
        else:
            # 如果不是全屏，设置一个合适的窗口大小
            master.geometry("1200x800")
            
        self.screen_width = master.winfo_screenwidth()
        self.screen_height = master.winfo_screenheight()

        self.resource_paths = resource_paths
        self.game_core = GameCore(resource_paths, self.screen_width, self.screen_height)
        master.configure(bg='#010101')  # 使用罕见颜色作为透明色
        master.wm_attributes("-transparentcolor", "#010101")
        # 窗口状态标志
        self._window_destroyed = False
        self.persistent_buttons = []
        self.current_choice_buttons = []
        
        # 新增：文本显示控制
        self.text_display_thread = None
        self.text_display_running = False
        self.current_full_text = ""
        self.text_display_speed = 50  # 每字符显示间隔(毫秒)
        self.auto_advance_delay = 3000  # 自动前进延迟(毫秒)
        self.auto_advance_timer = None
        
        # 新增：历史记录
        self.dialogue_history = []
        self.history_window = None
        
        # 新增：存档系统
        self.save_slots = {}
        self.current_save_slot = None

        # 显示加载屏幕
        self.show_loading_screen()
        master.after(100, self.load_and_init)

    def load_and_init(self):
        """加载数据并初始化UI"""
        try:
            self.load_initial_data()
        except Exception as e:
            messagebox.showerror("错误", f"数据加载失败: {str(e)}")
            self._destroy_window()
            return

        self.init_ui()
        self.update_chapter_display()

    def trigger_fight(self, fight_level):
        """启动独立战斗窗口"""
        fight_json_path = os.path.join(
            self.resource_paths["dialogues"],
            "战斗关卡",
            f"{fight_level}.json"
        )

        try:
            from fight import FightGame
            # 创建非模态窗口（主窗口保持响应）
            fight_window = FightGame(fight_json_path, parent=self.master, fullscreen=True)
            
            # 暂停当前剧情播放
            self.stop_text_display()
            if self.auto_advance_timer:
                self.master.after_cancel(self.auto_advance_timer)
                self.auto_advance_timer = None

            # 设置回调函数处理战斗结果
            def check_fight_result():
                if fight_window.result is not None:
                    self.handle_fight_result(fight_window.result)
                else:
                    self.master.after(100, check_fight_result)

            check_fight_result()

        except Exception as e:
            messagebox.showerror("战斗系统错误", f"无法启动战斗: {str(e)}")
            # 如果战斗启动失败，继续剧情
            self.next_dialogue()

    def handle_fight_result(self, result):
        """处理战斗结果"""
        if result == "victory":
            # 更新剧情到胜利分支
            self.current_node = "战斗胜利后节点"
        else:
            # 更新剧情到失败分支
            self.current_node = "战斗失败后节点"

        # 确保按钮可见
        self.ensure_buttons_visible()

        # 继续剧情
        self.next_dialogue()

    def show_loading_screen(self):
        """显示加载屏幕"""
        self.bg_canvas = tk.Canvas(self.master, width=self.screen_width, height=self.screen_height)
        self.bg_canvas.pack()
        self.bg_canvas.create_text(
            self.screen_width / 2, self.screen_height / 2,
            text="加载中...",
            font=("微软雅黑", 36),
            fill="white"
        )

    def _destroy_window(self):
        """安全销毁窗口的方法"""
        if not self._window_destroyed and self.master.winfo_exists():
            self._window_destroyed = True
            self.master.destroy()

    def load_initial_data(self):
        """加载初始游戏数据"""
        self.game_core.load_game_data()
        self.game_core.preload_resources()

    def init_ui(self):
        """初始化用户界面"""
        if self._window_destroyed:
            return

        # 清除加载屏幕
        self.bg_canvas.destroy()

        self.bg_canvas = tk.Canvas(self.master, width=self.screen_width, height=self.screen_height)
        self.bg_canvas.pack()

        # 创建角色立绘框架 - 修改背景为透明
        self.char_frames = {}
        for char_id in ["1", "2", "3", "4"]:  # 增加到4个角色框架
            frame = tk.Label(
                self.master,
                bd=0,
                bg='#010101',  # 使用与主窗口相同的透明色
                highlightthickness=0
            )
            frame.place(relx=0.5, rely=0.45, anchor="center")  # 向上移动 (从0.6改为0.45)
            self.char_frames[char_id] = frame

        self.setup_dialogue_box()
        self.setup_settings_button()
        self.bind_events()
        
        # 确保对话框背景正确显示
        self.master.after(100, self.update_dialogue_background)

    def update_dialogue_background(self):
        """更新对话框背景，确保完全覆盖"""
        if self._window_destroyed or not hasattr(self, 'dialogue_canvas'):
            return
            
        canvas_width = int(0.95 * self.screen_width)
        canvas_height = int(0.25 * self.screen_height)
        
        # 清除现有背景
        self.dialogue_canvas.delete("background")
        
        # 重新创建背景
        if self.game_core.ui_background_loaded and "dialogue_box" in self.game_core.ui_backgrounds:
            bg_image = self.game_core.ui_backgrounds["dialogue_box"]
            self.dialogue_bg = self.dialogue_canvas.create_image(
                0, 0,
                image=bg_image,
                anchor="nw",
                tags="background"
            )
        else:
            self.dialogue_bg = self.dialogue_canvas.create_rectangle(
                0, 0, canvas_width, canvas_height,
                fill="#1a1a1a", outline="",
                tags="background"
            )
        
        # 确保背景在最底层
        self.dialogue_canvas.tag_lower("background")

    def setup_dialogue_box(self):
        """创建对话框"""
        if self._window_destroyed:
            return

        # 先销毁旧的对话框画布（如果存在）
        if hasattr(self, 'dialogue_canvas'):
            self.dialogue_canvas.destroy()

        # 重新创建对话框画布 - 确保背景图片完全覆盖
        canvas_width = int(0.95 * self.screen_width)
        canvas_height = int(0.25 * self.screen_height)
        
        self.dialogue_canvas = tk.Canvas(self.master,
                                         width=canvas_width,
                                         height=canvas_height,
                                         bg='#010101',  # 使用透明色
                                         highlightthickness=0,  # 移除边框
                                         bd=0)  # 移除边框
        self.dialogue_canvas.place(relx=0.5, rely=0.85, anchor="center")

        # **使用最新的UI背景资源 - 确保图片完全覆盖画布**
        self.update_dialogue_background()

        # 重新创建文本和名字标签 - 调整位置确保在背景内
        self.text_item = self.dialogue_canvas.create_text(
            50, 80, font=("微软雅黑", int(self.screen_height * 0.028)),
            fill="#FF3333", width=canvas_width - 100, anchor="nw",  # 调整文字区域宽度
            justify=tk.LEFT
        )
        
        # 修改名字标签背景为透明
        self.name_label = tk.Label(self.dialogue_canvas,
                                   font=("微软雅黑", int(self.screen_height * 0.032)),
                                   bg='#010101',  # 使用透明色
                                   fg="#FF3333")
        self.name_label.place(x=50, y=20)

    def setup_settings_button(self):
        """创建设置按钮"""
        if self._window_destroyed:
            return

        # 创建设置按钮
        self.settings_button = tk.Button(self.master, text="设置",
                                        command=self.show_settings_dialog,
                                        font=("微软雅黑", 16),
                                        bg="#1a1a1a", fg="#ffffff", bd=0,
                                        padx=20, pady=10)
        self.settings_button.place(relx=0.9, rely=0.92, anchor="center")  # 调整位置到对话框下方
        
        # 创建历史记录按钮
        self.history_button = tk.Button(self.master, text="历史",
                                       command=self.show_history,
                                       font=("微软雅黑", 16),
                                       bg="#1a1a1a", fg="#ffffff", bd=0,
                                       padx=20, pady=10)
        self.history_button.place(relx=0.8, rely=0.92, anchor="center")  # 调整位置到对话框下方
        
        # 创建存档按钮
        self.save_button = tk.Button(self.master, text="存档",
                                    command=self.show_save_load_dialog,
                                    font=("微软雅黑", 16),
                                    bg="#1a1a1a", fg="#ffffff", bd=0,
                                    padx=20, pady=10)
        self.save_button.place(relx=0.7, rely=0.92, anchor="center")  # 调整位置到对话框下方
        
        # 将按钮添加到持久按钮列表
        self.persistent_buttons.extend([self.settings_button, self.history_button, self.save_button])

    def ensure_buttons_visible(self):
        """确保按钮可见"""
        if self._window_destroyed:
            return
            
        # 检查按钮是否存在，如果不存在则重新创建
        if not hasattr(self, 'settings_button') or not self.settings_button.winfo_exists():
            self.setup_settings_button()
        else:
            # 确保按钮在最前面
            self.settings_button.lift()
            self.history_button.lift()
            self.save_button.lift()

    def show_settings_dialog(self):
        """显示设置对话框"""
        if self._window_destroyed:
            return

        # 创建设置窗口
        settings_window = tk.Toplevel(self.master)
        settings_window.title("游戏设置")
        settings_window.geometry("400x500")
        settings_window.configure(bg="#1a1a1a")
        settings_window.resizable(False, False)
        
        # 居中显示
        settings_window.transient(self.master)
        settings_window.grab_set()

        # 文本显示速度设置
        tk.Label(settings_window, text="文本显示速度", font=("微软雅黑", 14), 
                bg="#1a1a1a", fg="#ffffff").pack(pady=10)
        
        speed_var = tk.IntVar(value=self.text_display_speed)
        speed_scale = tk.Scale(settings_window, from_=10, to=200, orient=tk.HORIZONTAL,
                              variable=speed_var, bg="#1a1a1a", fg="#ffffff",
                              highlightthickness=0, troughcolor="#333333")
        speed_scale.pack(pady=5)

        # 自动前进延迟设置
        tk.Label(settings_window, text="自动前进延迟(秒)", font=("微软雅黑", 14),
                bg="#1a1a1a", fg="#ffffff").pack(pady=10)
        
        delay_var = tk.IntVar(value=self.auto_advance_delay // 1000)
        delay_scale = tk.Scale(settings_window, from_=1, to=10, orient=tk.HORIZONTAL,
                              variable=delay_var, bg="#1a1a1a", fg="#ffffff",
                              highlightthickness=0, troughcolor="#333333")
        delay_scale.pack(pady=5)

        # 音量设置
        tk.Label(settings_window, text="背景音乐音量", font=("微软雅黑", 14),
                bg="#1a1a1a", fg="#ffffff").pack(pady=10)
        
        bgm_var = tk.DoubleVar(value=self.game_core.bgm_volume)
        bgm_scale = tk.Scale(settings_window, from_=0.0, to=1.0, resolution=0.1,
                            orient=tk.HORIZONTAL, variable=bgm_var, bg="#1a1a1a", fg="#ffffff",
                            highlightthickness=0, troughcolor="#333333")
        bgm_scale.pack(pady=5)

        tk.Label(settings_window, text="音效音量", font=("微软雅黑", 14),
                bg="#1a1a1a", fg="#ffffff").pack(pady=10)
        
        sfx_var = tk.DoubleVar(value=self.game_core.sfx_volume)
        sfx_scale = tk.Scale(settings_window, from_=0.0, to=1.0, resolution=0.1,
                            orient=tk.HORIZONTAL, variable=sfx_var, bg="#1a1a1a", fg="#ffffff",
                            highlightthickness=0, troughcolor="#333333")
        sfx_scale.pack(pady=5)

        # 保存按钮
        def save_settings():
            self.text_display_speed = speed_var.get()
            self.auto_advance_delay = delay_var.get() * 1000
            self.game_core.bgm_volume = bgm_var.get()
            self.game_core.sfx_volume = sfx_var.get()
            
            # 更新当前音乐音量
            if self.game_core.current_bgm:
                pygame.mixer.music.set_volume(self.game_core.bgm_volume)
            
            settings_window.destroy()

        save_btn = tk.Button(settings_window, text="保存设置", command=save_settings,
                            font=("微软雅黑", 12), bg="#4CAF50", fg="#ffffff",
                            bd=0, padx=30, pady=10)
        save_btn.pack(pady=20)

    def bind_events(self):
        """绑定交互事件"""
        if self._window_destroyed:
            return

        self.dialogue_canvas.bind("<Button-1>", self.next_dialogue)
        self.master.bind("<Escape>", lambda e: self._destroy_window())
        
        # 新增键盘快捷键
        self.master.bind("<space>", self.next_dialogue)  # 空格键前进
        self.master.bind("<Return>", self.next_dialogue)  # 回车键前进
        self.master.bind("<Right>", self.next_dialogue)  # 右箭头前进
        self.master.bind("<h>", lambda e: self.show_history())  # H键显示历史
        self.master.bind("<s>", lambda e: self.show_save_load_dialog())  # S键存档
        self.master.bind("<o>", lambda e: self.show_settings_dialog())  # O键设置

    def update_chapter_display(self):
        """更新章节显示"""
        if self._window_destroyed:
            return

        if self.game_core.current_chapter >= len(self.game_core.game_data["chapters"]):
            self.show_ending()
            return

        chapter = self.game_core.game_data["chapters"][self.game_core.current_chapter]
        print(f"加载章节: {chapter.get('title', '未命名章节')}")

        self.show_background(chapter["background"])
        self.game_core.play_bgm(chapter.get("music"))
        self.current_dialogue_idx = 0

        # **新增：初始化对话框文本为空，避免显示旧内容**
        self.dialogue_canvas.itemconfig(self.text_item, text="")
        self.name_label.config(text="")

        # 确保按钮可见
        self.ensure_buttons_visible()

        # 显示当前对话
        self.show_current_dialogue()

    def show_background(self, filename):
        if self._window_destroyed:
            return

        self.bg_canvas.delete("all")
        self.bg_canvas.create_image(0, 0,
                                    image=self.game_core.backgrounds[filename],
                                    anchor="nw")

        # 通知监听程序更新背景
        with open("background_update.txt", "w") as f:
            f.write(os.path.join(self.resource_paths["images"], filename))

    def show_current_dialogue(self):
        """显示当前对话"""
        if self._window_destroyed:
            return

        chapter = self.game_core.game_data["chapters"][self.game_core.current_chapter]

        if self.current_dialogue_idx >= len(chapter["dialogues"]):
            # 检查章节是否有选择项
            if "choices" in chapter:
                self.show_choices(chapter["choices"])
            else:
                # 没有更多对话，进入下一章节
                self.game_core.current_chapter += 1
                self.update_chapter_display()
            return

        dialogue = chapter["dialogues"][self.current_dialogue_idx]
        self.show_dialogue(dialogue)

    def show_dialogue(self, dialogue):
        """显示对话内容"""
        if self._window_destroyed:
            return

        # 停止之前的文本显示
        self.stop_text_display()

        # 确保按钮可见
        self.ensure_buttons_visible()

        # 确保active是字符串类型
        active_char = str(dialogue["active"])

        # 隐藏所有角色 - 改进隐藏逻辑
        for char_id in self.char_frames:
            frame = self.char_frames[char_id]
            frame.config(image=None)
            frame.image = None  # 清除图片引用
            # 将框架移到屏幕外，避免显示空白框
            frame.place_forget()

        # 确保角色立绘已加载
        if active_char not in self.game_core.characters:
            active_char = "2"  # 默认使用角色2
            if active_char not in self.game_core.characters:
                print("错误: 角色2未定义")
                return

        # 显示当前角色
        if "sprite" in dialogue:
            sprite_name = dialogue["sprite"]
            if active_char not in self.game_core.character_sprites or \
                    sprite_name not in self.game_core.character_sprites[active_char]:
                print(f"加载特殊立绘: {sprite_name}")
                self.game_core.load_character(active_char, sprite_name, is_sprite=True)
            img = self.game_core.character_sprites[active_char][sprite_name]
        elif "emotion" in dialogue:
            # 处理表情系统
            emotion = dialogue["emotion"]
            img = self.get_character_emotion(active_char, emotion)
        else:
            img = self.game_core.characters[active_char]["normal"]

        # 调整立绘位置 - 改进位置计算
        if active_char == "1":
            relx, rely, anchor = 0.05, 0.6, "w"  # 左侧
        elif active_char == "2":
            relx, rely, anchor = 0.95, 0.6, "e"  # 右侧
        elif active_char == "3":
            relx, rely, anchor = 0.25, 0.6, "center"  # 左中
        else:  # char_id == "4"
            relx, rely, anchor = 0.75, 0.6, "center"  # 右中

        # 只有当有图片时才显示框架
        if img:
            self.char_frames[active_char].place(relx=relx, rely=rely, anchor=anchor)
            self.char_frames[active_char].config(image=img)
            self.char_frames[active_char].image = img  # 防止被垃圾回收

        # 更新对话框
        char_data = self.game_core.game_data["characters"].get(
            active_char, {"name": "未知角色", "color": "#FFFFFF"}
        )
        self.name_label.config(text=char_data["name"], fg=char_data["color"])
        
        # 开始逐字显示文本 - 添加安全检查
        if "text" in dialogue:
            self.current_full_text = dialogue["text"]
            self.start_text_display()
            
            # 添加到历史记录
            self.add_to_history(char_data["name"], dialogue["text"])
        else:
            # 如果没有文本，直接显示空内容
            self.current_full_text = ""
            self.dialogue_canvas.itemconfig(self.text_item, text="")
            # 立即启动自动前进
            self._start_auto_advance()

        # 处理背景切换
        if "background" in dialogue:
            self.show_background(dialogue["background"])

        # 播放音效和特效
        if "sound" in dialogue:
            self.game_core.play_sound(dialogue["sound"])
        if "effect" in dialogue:
            self.handle_effect(dialogue["effect"])

        # 检测战斗事件
        if "fight" in dialogue:
            fight_level = dialogue["fight"]
            self.master.after(100, lambda: self.trigger_fight(fight_level))
            return

        # 检查是否有选择项
        if "choices" in dialogue:
            self.master.after(100, lambda: self.show_choices(dialogue["choices"]))

    def start_text_display(self):
        """开始逐字显示文本"""
        if self.text_display_running:
            return
            
        self.text_display_running = True
        self.text_display_thread = threading.Thread(target=self._text_display_worker)
        self.text_display_thread.daemon = True
        self.text_display_thread.start()

    def stop_text_display(self):
        """停止文本显示"""
        self.text_display_running = False
        if self.auto_advance_timer:
            self.master.after_cancel(self.auto_advance_timer)
            self.auto_advance_timer = None

    def _text_display_worker(self):
        """文本显示工作线程"""
        displayed_text = ""
        for char in self.current_full_text:
            if not self.text_display_running:
                break
            displayed_text += char
            # 在主线程中更新UI
            self.master.after(0, lambda t=displayed_text: self._update_text_display(t))
            time.sleep(self.text_display_speed / 1000.0)
        
        # 显示完成后启动自动前进
        if self.text_display_running:
            self.master.after(0, self._start_auto_advance)

    def _update_text_display(self, text):
        """更新文本显示"""
        if not self._window_destroyed:
            # 确保文字完整显示，不截断
            self.dialogue_canvas.itemconfig(self.text_item, text=text)
            # 强制更新画布
            self.dialogue_canvas.update_idletasks()

    def _start_auto_advance(self):
        """启动自动前进"""
        if not self._window_destroyed:
            self.auto_advance_timer = self.master.after(self.auto_advance_delay, self.next_dialogue)

    def next_dialogue(self, event=None):
        """显示下一个对话"""
        if self._window_destroyed:
            return

        # 如果文本还在显示中，点击跳过显示
        if self.text_display_running:
            self.stop_text_display()
            self.dialogue_canvas.itemconfig(self.text_item, text=self.current_full_text)
            # 立即启动自动前进
            self._start_auto_advance()
            return

        self.current_dialogue_idx += 1
        self.show_current_dialogue()

    def handle_effect(self, effect):
        """处理特效"""
        if self._window_destroyed:
            return

        if effect == "画面震动":
            self.shake_screen(5, 200)
        elif effect == "特写镜头":
            self.zoom_character()
        elif effect == "淡入":
            self.fade_in()
        elif effect == "淡出":
            self.fade_out()
        elif effect == "闪烁":
            self.flash_screen()
        elif effect == "慢动作":
            self.slow_motion()

    def shake_screen(self, amplitude, duration):
        """屏幕震动效果"""
        if self._window_destroyed:
            return

        original_x = self.master.winfo_x()
        original_y = self.master.winfo_y()

        for i in range(0, duration, 50):
            offset_x = amplitude * (-1) ** int(i / 50)
            offset_y = amplitude * (-1) ** (int(i / 50) + 1)
            self.master.geometry(f"+{original_x + offset_x}+{original_y + offset_y}")
            self.master.update()
            self.master.after(50)

        self.master.geometry(f"+{original_x}+{original_y}")

    def zoom_character(self):
        """角色特写效果"""
        # 实现角色放大效果
        pass

    def fade_in(self):
        """淡入效果"""
        # 实现淡入效果
        pass

    def fade_out(self):
        """淡出效果"""
        # 实现淡出效果
        pass

    def flash_screen(self):
        """屏幕闪烁效果"""
        if self._window_destroyed:
            return

        # 创建白色覆盖层
        flash_canvas = tk.Canvas(self.master, width=self.screen_width, height=self.screen_height,
                                bg="white", highlightthickness=0)
        flash_canvas.place(x=0, y=0)
        
        # 闪烁动画
        def flash_animation(alpha=255):
            if alpha <= 0:
                flash_canvas.destroy()
                return
            flash_canvas.configure(bg=f"#{alpha:02x}{alpha:02x}{alpha:02x}")
            self.master.after(50, lambda: flash_animation(alpha - 25))
        
        flash_animation()

    def slow_motion(self):
        """慢动作效果"""
        # 临时降低文本显示速度
        original_speed = self.text_display_speed
        self.text_display_speed = 200
        
        # 3秒后恢复正常速度
        self.master.after(3000, lambda: setattr(self, 'text_display_speed', original_speed))

    def show_choices(self, choices):
        """显示选择项"""
        if self._window_destroyed:
            return

        # 确保按钮可见
        self.ensure_buttons_visible()

        # 清除现有选择按钮
        for widget in self.master.winfo_children():
            if isinstance(widget, tk.Button) and widget not in self.persistent_buttons:
                widget.destroy()

        # 创建选择按钮 - 改进自适应布局
        # 计算按钮区域，确保在对话框上方
        dialogue_height = 0.25 * self.screen_height
        dialogue_y = 0.85 * self.screen_height  # 更新对话框位置
        available_height = dialogue_y - 100  # 留出一些边距
        
        # 改进按钮大小计算
        max_text_length = max(len(choice["text"]) for choice in choices)
        num_choices = len(choices)
        
        # 根据文本长度和选项数量动态计算按钮尺寸
        if max_text_length <= 20:
            button_width = int(self.screen_width * 0.4)  # 短文本
            font_size = 20
        elif max_text_length <= 40:
            button_width = int(self.screen_width * 0.5)  # 中等文本
            font_size = 18
        else:
            button_width = int(self.screen_width * 0.6)  # 长文本
            font_size = 16
        
        # 计算每行大约能容纳的字符数
        chars_per_line = button_width // (font_size * 0.6)  # 估算字符宽度
        
        # 计算每个按钮需要的行数
        button_heights = []
        for choice in choices:
            text = choice["text"]
            lines_needed = max(1, len(text) // chars_per_line + (1 if len(text) % chars_per_line > 0 else 0))
            button_height = 80 + (lines_needed - 1) * 35  # 增加基础高度从60到80，每行额外高度从30到35
            button_heights.append(button_height)
        
        # 计算总高度和间距
        total_height = sum(button_heights) + (num_choices - 1) * 50  # 增加间距从40到50
        
        # 如果总高度超过可用空间，调整按钮大小
        if total_height > available_height:
            scale_factor = available_height / total_height
            button_heights = [int(h * scale_factor) for h in button_heights]
            font_size = max(12, int(font_size * scale_factor))  # 最小字体12
        
        # 计算起始Y位置（居中）
        current_y = (available_height - sum(button_heights) - (num_choices - 1) * 50) // 2 + 50

        # 自定义按钮样式 - 动态调整
        button_style = {
            "font": ("微软雅黑", font_size),
            "bg": "#1a1a1a",
            "fg": "#ffffff",
            "bd": 0,
            "padx": 50,  # 增加水平内边距从30到50
            "pady": 25,  # 增加垂直内边距从15到25
            "relief": tk.FLAT,
            "wraplength": button_width - 100,  # 调整换行宽度（减去左右内边距）
            "justify": tk.CENTER,
            "width": button_width // (font_size * 0.6),  # 设置按钮宽度
        }

        # 如果有UI背景，使用背景图片
        if self.game_core.ui_background_loaded:
            button_style["image"] = self.game_core.ui_backgrounds["button_normal"]
            button_style["compound"] = tk.CENTER

        # 存储创建的按钮
        self.current_choice_buttons = []

        for i, choice in enumerate(choices):
            btn = tk.Button(self.master, text=choice["text"],
                            command=lambda n=choice["next_chapter"]: self.select_choice(n),
                            **button_style)

            # 添加悬停效果
            if self.game_core.ui_background_loaded:
                btn.bind("<Enter>", lambda e, b=btn: b.config(
                    image=self.game_core.ui_backgrounds["button_hover"],
                    bg="#333333",
                    fg="#ffffff"
                ))
                btn.bind("<Leave>", lambda e, b=btn: b.config(
                    image=self.game_core.ui_backgrounds["button_normal"],
                    bg="#1a1a1a",
                    fg="#ffffff"
                ))

            # 设置按钮高度
            btn.config(height=button_heights[i] // 30)  # 转换为行数

            # 放置按钮
            btn.place(x=self.screen_width // 2, y=current_y, anchor="center")
            btn.image = button_style.get("image")
            self.current_choice_buttons.append(btn)
            
            # 更新下一个按钮的Y位置
            current_y += button_heights[i] + 50

    def select_choice(self, next_chapter):
        """处理选择"""
        if self._window_destroyed:
            return

        print(f"选择分支: {next_chapter}")

        # 清除选择按钮
        for btn in self.current_choice_buttons:
            if btn.winfo_exists():
                btn.destroy()
        self.current_choice_buttons = []

        try:
            # 1. 清除背景和角色立绘，但保留对话框
            self.bg_canvas.delete("all")
            for char_frame in self.char_frames.values():
                char_frame.config(image=None)

            # 2. 加载新章节数据
            self.game_core.load_game_data(next_chapter)
            self.game_core.preload_resources()

            # 3. 重置章节状态
            self.game_core.current_chapter = 0
            self.current_dialogue_idx = 0

            # 4. 更新对话框背景（如果有变化）
            self.update_dialogue_background()

            # 5. 确保按钮可见
            self.ensure_buttons_visible()

            # 6. 显示新章节的第一条对话
            self.update_chapter_display()

        except FileNotFoundError as e:
            import os
            missing_file = os.path.basename(str(e))
            messagebox.showerror("资源缺失", f"缺少关键文件：{missing_file}")
            return
        except Exception as e:
            messagebox.showerror("错误", f"章节加载失败：{str(e)}")
            return

    def show_ending(self):
        """显示结局"""
        if self._window_destroyed:
            return

        self.bg_canvas.delete("all")
        self.bg_canvas.create_text(self.screen_width / 2, self.screen_height / 2,
                                   text="游戏结束，感谢游玩！",
                                   font=("微软雅黑", 48), fill="white")
        self.game_core.play_bgm(None)  # 停止背景音乐

    def add_to_history(self, name, text):
        """添加到历史记录"""
        self.dialogue_history.append((name, text))

    def show_history(self):
        """显示历史记录"""
        if self._window_destroyed or self.history_window:
            return

        # 创建历史记录窗口
        self.history_window = tk.Toplevel(self.master)
        self.history_window.title("对话历史")
        self.history_window.geometry("800x600")
        self.history_window.configure(bg="#1a1a1a")
        
        # 居中显示
        self.history_window.transient(self.master)
        self.history_window.grab_set()

        # 创建滚动文本框
        text_frame = tk.Frame(self.history_window, bg="#1a1a1a")
        text_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

        scrollbar = tk.Scrollbar(text_frame)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        history_text = tk.Text(text_frame, wrap=tk.WORD, yscrollcommand=scrollbar.set,
                              bg="#1a1a1a", fg="#ffffff", font=("微软雅黑", 12),
                              insertbackground="#ffffff", selectbackground="#333333")
        history_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        scrollbar.config(command=history_text.yview)

        # 插入历史记录
        for name, text in self.dialogue_history:
            history_text.insert(tk.END, f"{name}: {text}\n\n")
            history_text.see(tk.END)

        # 关闭按钮
        close_btn = tk.Button(self.history_window, text="关闭", 
                             command=self.close_history,
                             font=("微软雅黑", 12), bg="#f44336", fg="#ffffff",
                             bd=0, padx=30, pady=10)
        close_btn.pack(pady=10)

        # 窗口关闭事件
        self.history_window.protocol("WM_DELETE_WINDOW", self.close_history)

    def close_history(self):
        """关闭历史记录窗口"""
        if self.history_window:
            self.history_window.destroy()
            self.history_window = None

    def get_character_emotion(self, char_id, emotion):
        """获取角色表情"""
        if char_id not in self.game_core.characters:
            return None
            
        # 表情映射
        emotion_mapping = {
            "happy": "男主角若尘_得意.png",
            "sad": "男主角若尘_受伤.png",
            "angry": "男主角若尘_战斗.png",
            "thinking": "男主角若尘_思考.png",
            "dying": "男主角若尘_濒死.png",
            "awaken": "男主角若尘_觉醒.png"
        }
        
        if emotion in emotion_mapping:
            emotion_file = emotion_mapping[emotion]
            # 检查是否已加载
            if char_id not in self.game_core.character_sprites:
                self.game_core.character_sprites[char_id] = {}
            
            if emotion_file not in self.game_core.character_sprites[char_id]:
                self.game_core.load_character(char_id, emotion_file, is_sprite=True)
            
            return self.game_core.character_sprites[char_id][emotion_file]
        
        # 默认返回正常表情
        return self.game_core.characters[char_id]["normal"]

    def save_game(self, slot=1):
        """保存游戏"""
        save_data = {
            "chapter": self.game_core.current_chapter,
            "dialogue_idx": self.current_dialogue_idx,
            "history": self.dialogue_history,
            "timestamp": time.time()
        }
        
        try:
            import json
            with open(f"save_{slot}.json", "w", encoding="utf-8") as f:
                json.dump(save_data, f, ensure_ascii=False, indent=2)
            self.save_slots[slot] = save_data
            self.current_save_slot = slot
            messagebox.showinfo("保存成功", f"游戏已保存到存档槽 {slot}")
        except Exception as e:
            messagebox.showerror("保存失败", f"无法保存游戏: {str(e)}")

    def load_game(self, slot=1):
        """读取游戏"""
        try:
            import json
            with open(f"save_{slot}.json", "r", encoding="utf-8") as f:
                save_data = json.load(f)
            
            # 恢复游戏状态
            self.game_core.current_chapter = save_data["chapter"]
            self.current_dialogue_idx = save_data["dialogue_idx"]
            self.dialogue_history = save_data.get("history", [])
            
            # 重新加载当前章节
            self.update_chapter_display()
            messagebox.showinfo("读取成功", f"已从存档槽 {slot} 读取游戏")
            
        except FileNotFoundError:
            messagebox.showwarning("存档不存在", f"存档槽 {slot} 没有存档")
        except Exception as e:
            messagebox.showerror("读取失败", f"无法读取存档: {str(e)}")

    def show_save_load_dialog(self):
        """显示存档/读档对话框"""
        if self._window_destroyed:
            return

        # 创建存档/读档窗口
        save_window = tk.Toplevel(self.master)
        save_window.title("存档/读档")
        save_window.geometry("500x400")
        save_window.configure(bg="#1a1a1a")
        save_window.resizable(False, False)
        
        # 居中显示
        save_window.transient(self.master)
        save_window.grab_set()

        # 创建存档槽按钮
        for i in range(1, 6):  # 5个存档槽
            frame = tk.Frame(save_window, bg="#1a1a1a")
            frame.pack(fill=tk.X, padx=20, pady=5)
            
            # 存档槽信息
            try:
                import json
                with open(f"save_{i}.json", "r", encoding="utf-8") as f:
                    save_data = json.load(f)
                timestamp = time.strftime("%Y-%m-%d %H:%M", time.localtime(save_data["timestamp"]))
                info_text = f"存档槽 {i} - {timestamp}"
            except:
                info_text = f"存档槽 {i} - 空"
            
            tk.Label(frame, text=info_text, font=("微软雅黑", 12),
                    bg="#1a1a1a", fg="#ffffff").pack(side=tk.LEFT)
            
            # 保存按钮
            save_btn = tk.Button(frame, text="保存", 
                               command=lambda s=i: self.save_game(s),
                               font=("微软雅黑", 10), bg="#4CAF50", fg="#ffffff",
                               bd=0, padx=15, pady=5)
            save_btn.pack(side=tk.RIGHT, padx=5)
            
            # 读取按钮
            load_btn = tk.Button(frame, text="读取",
                               command=lambda s=i: self.load_game(s),
                               font=("微软雅黑", 10), bg="#2196F3", fg="#ffffff",
                               bd=0, padx=15, pady=5)
            load_btn.pack(side=tk.RIGHT, padx=5)

        # 关闭按钮
        close_btn = tk.Button(save_window, text="关闭",
                            command=save_window.destroy,
                            font=("微软雅黑", 12), bg="#f44336", fg="#ffffff",
                            bd=0, padx=30, pady=10)
        close_btn.pack(pady=20)


if __name__ == "__main__":
    root = tk.Tk()
    try:
        from ctypes import windll

        windll.shcore.SetProcessDpiAwareness(1)
    except:
        pass

    resource_paths = {
        "images": "images",
        "sounds": "sounds",
        "dialogues": "dialogues"
    }

    # 检查命令行参数
    fullscreen = "--fullscreen" in sys.argv

    # 使用try-except捕获初始化过程中的任何异常
    try:
        app = VisualNovelUI(root, resource_paths, fullscreen=fullscreen)
        root.mainloop()
    except Exception as e:
        messagebox.showerror("致命错误", f"游戏无法启动:\n{str(e)}")
        root.destroy()